package net.retorx

import java.io.{FileWriter, File}
import net.retorx.util.ImageUtil._
import collection.mutable._
import com.google.inject.{Inject, Singleton}
import com.google.inject.name.Named
import collection.mutable
import java.util.Properties
import collection.JavaConversions._

@Singleton
class ImageContentDAO @Inject() (imageContentBuilder: ImageContentBuilder) {

	private val sortFunction = (imageA: ImageContent, imageB: ImageContent) => (imageA.sortByDate(imageB))

	private val imageContentByName = mutable.HashMap[String, ImageContent]()
	private val imageContentByTag = mutable.HashMap[String, ListBuffer[ImageContent]]()
	private val imageContentList = ListBuffer[ImageContent]()
    private val tags = ListBuffer[String]()

	def reload(images:collection.Iterable[ImageContent]) {
		imageContentList.clear()
		imageContentByName.clear()
		imageContentByTag.clear()
        tags.clear()

        imageContentBuilder.getTags.foreach(tag => tags.add(tag.trim()))

        images.foreach(imageContent => addImageContent(imageContent))
		sortImagesLists()
	}

    def reloadTags() {
        val copyOfImages = imageContentList.clone()
        reload(copyOfImages)
    }

    def reloadFromFiles() {
        reload(imageContentBuilder.getImagesFromContentDir)
    }

    private def sortImagesLists() {
        sortImages(imageContentList)
        imageContentByTag.values.foreach(list => {
            sortImages(list)
        })
    }

    private def sortImages(list: ListBuffer[ImageContent]) = {
        val sorted = list.sortWith(sortFunction)
        list.clear()
        list ++= sorted
    }

	def addImageContent(imageContent: ImageContent) = {
        imageContentByName(imageContent.getName()) = imageContent
        handleImageContentTags(imageContent)
        imageContentList + imageContent
	}

    private def handleImageContentTags(imageContent: ImageContent) {
        imageContent.getTags.foreach(tag => {
            val trimmedTag = tag.trim()
            if ( ! tags.contains(trimmedTag)) {
                tags.add(trimmedTag)
            }
            val imageContentsForTag = imageContentByTag.getOrElseUpdate(trimmedTag, new ListBuffer[ImageContent]())
            imageContentsForTag + imageContent
        })
    }

    def renameTag(existingTag: String, newTag: String) {
        imageContentByTag.remove(existingTag) match {
            case Some(imagesForExistingTag) => {
                val images = imageContentByTag.get(newTag) match {
                    case Some(imagesForNewTag) => imagesForNewTag ++ imagesForExistingTag
                    case None => imagesForExistingTag
                }

                imageContentByTag += newTag -> images
                imagesForExistingTag.foreach(imageContent => {
                    imageContent.replaceTag(existingTag, newTag)
                    savePropertiesFile(imageContent)
                })
            }
            case None =>
        }
    }

	def getTags = {
        tags
	}

	def getImageContentByTag(tag: String) = {
		imageContentByTag.getOrElse(tag, new ListBuffer())
	}

	def getAllImageContent = {
		imageContentList
	}

	def getImageContent(id: String) = {
		imageContentByName(id)
	}

	def getLatestImages = {
		val tags = imageContentList.head.getTags
		getImageContentByTag(tags(0))
	}

    def savePropertiesFile(imageContent:ImageContent) {
        val propertiesToSave = new Properties()
        propertiesToSave.putAll(imageContent.getProperties)
        val propertyFile = new File(imageContent.directory, "info.properties")
        propertiesToSave.store(new FileWriter(propertyFile), "")
    }
}

